// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;
import NotifyMgr from "../base/notify/NotifyMgr"
import {SelfNotification} from "../base/notify/NotifyMgr"
import TransformComponent from "../base/ECSR/components/TransformComponent"
import MapComponent from "./components/MapComponent"
import BubbleComponent from "./components/BubbleComponent"
// import MoveRenderer from "./renderers/TestMoveRenderer";
import SimulationManager from "../base/lockStep/SimulationManager";
import EntityWorld from "../base/ECSR/EntityWorld";
import GameClientData from "./data/GameClientData";
import Notifications from "./Notifications"
import AimRenderer from "./renderers/AimRenderer";
import MapLayer from "./MapLayer"
import MovePathRenderer from "./renderers/MovePathRenderer";

@ccclass
export default class GameEntitySpawn extends cc.Component {
    @property(cc.Node)
    FXLayer:cc.Node = null;
    @property(cc.Node)
    mapLayer:cc.Node = null;

    resInit:boolean = false;
    bubblePrefab: cc.Prefab = null;

    nodes:Map<string, cc.Node> = new Map<string, cc.Node>();
    listCreateEntity:Array<string> = new Array<string>();
    listRemoveEntity:Array<string> = new Array<string>();

    adjustBubble:cc.Node = null;

    OnCreateMap(note:SelfNotification)
    {
        cc.log("EntitySpawn|OnCreateEntity");
        let world = SimulationManager.Instance().GetSimulation(GameClientData.simId).GetEntityWorld();
        let mapCom = note.params[0] as MapComponent;
        this.mapLayer.setPosition(mapCom.position);

        for(let i = 0; i < mapCom.bubbleMap.length; ++i)
        {
            for(let j = 0;j < mapCom.bubbleMap[i].length; ++j)
            {
                let id = mapCom.bubbleMap[i][j];
                if(id === null) continue;

                let transCom = world.GetComponentByEntityId(id, "TransformComponent") as TransformComponent;
                let bubbCom = world.GetComponentByEntityId(id, "BubbleComponent") as BubbleComponent;

                let node:cc.Node = cc.instantiate(this.bubblePrefab);
                node.setPosition(transCom.GetPosition());
                let bubble = node.getComponent("Bubble");
                bubble.type = bubbCom.colorType;
                bubble.row = bubbCom.row;
                bubble.col = bubbCom.col;
                node.parent = this.mapLayer;
                // node.parent = this.node.parent;

                this.nodes.set(id, node);
            }
        }
    }

    OnCreateReadBubble(note:SelfNotification)
    {
        cc.log("EntitySpawn|OnCreateReadBubble");
        let world = SimulationManager.Instance().GetSimulation(GameClientData.simId).GetEntityWorld();
        let bubbleCom = note.params[0] as BubbleComponent;
        let id = bubbleCom.entityId;
        let transCom = world.GetComponentByEntityId(id, "TransformComponent") as TransformComponent;

        let node:cc.Node = cc.instantiate(this.bubblePrefab);
        let aimRenderer = node.addComponent(AimRenderer);
        aimRenderer.SetEntityId(id);
        aimRenderer.simulation = SimulationManager.Instance().GetSimulation(GameClientData.simId);

        let movePathRenderer = node.addComponent(MovePathRenderer);
        movePathRenderer.SetEntityId(id);
        movePathRenderer.simulation = SimulationManager.Instance().GetSimulation(GameClientData.simId);

        node.addComponent(cc.Graphics);

        node.setPosition(transCom.GetPosition());
        let bubble = node.getComponent("Bubble");
        bubble.type = bubbleCom.colorType;
        node.parent = this.node;
        this.nodes.set(id, node);
    }

    OnCreateNormalBubble(note:SelfNotification)
    {
        cc.log("EntitySpawn|OnCreateNormalBubble");
        let id = note.params[0] as string;
        let pos = note.params[1] as cc.Vec2;

        let node:cc.Node = cc.instantiate(this.bubblePrefab);
        node.setPosition(pos);

        // let bubble = node.getComponent("Bubble");
        // bubble.type = bubbleCom.colorType;
        node.parent = this.node;

        this.nodes.set(id, node);
    }

    
    OnRemoveEntity(note:SelfNotification)
    {
        cc.log("OnRemoveEntityFromThread");
        let id = note.params[0] as string;
        this.listRemoveEntity.push(id);
    }

    CreateNewEntityGO(id:string)
    {
        cc.log("EntitySpawn|CreateNewEntityGO");
        // let node:cc.Node = cc.instantiate(this.ball);
        // let renderers = node.addComponent(MoveRenderer);
        // // PlayerInfoDisplayActionRenderer red = obj.GetComponent<PlayerInfoDisplayActionRenderer>();
        // // red.SetEntityId(id);
        // renderers.SetEntityId(id);
        // renderers.simulation = SimulationManager.Instance().GetSimulation("123");

        // node.setPosition(0, 0);
        // node.parent = this.node.parent;

        // this.nodes.set(id, node);
    }
    
    RmoveEntityGo(id:string)
    {
        cc.log("GameEntitySpawn|RemoveEntityGo|" + id);
        if(this.nodes.has(id))
        {
            let node = this.nodes.get(id);
            node.parent = null;
            this.nodes.delete(id);
        }
    }

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        cc.log("GameEntitySpawn|onLoad");
        let me = this;
        cc.resources.load("prefabs/Bubble",  cc.Prefab, (error:Error, bubblePrefab:cc.Prefab)=>{
            if(bubblePrefab === undefined)
            {
                cc.log("GameEntitySpawn|" + error.message);
            }
            me.bubblePrefab = bubblePrefab;
            me.resInit = true;
        });

        NotifyMgr.Instance().AddListener(Notifications.LoadMap, 
            (note)=>{ me.OnCreateMap(note); });
        NotifyMgr.Instance().AddListener(Notifications.CreateReadBubble, (note)=>{ me.OnCreateReadBubble(note); });
        NotifyMgr.Instance().AddListener(Notifications.CreateNormalBubble, (note)=>{ me.OnCreateNormalBubble(note); });
        NotifyMgr.Instance().AddListener(Notifications.RemoveEntity, (note)=>{ me.OnRemoveEntity(note); });
    }

    start () {

    }

    update (dt) {
        while(this.listRemoveEntity.length > 0)
        {
            let id = this.listRemoveEntity.pop();
            this.RmoveEntityGo(id);
        }
    }
}
